#!/bin/bash
# MinIO连接检查和修复工具
# 版本: 1.0.0

# 记录当前工作目录
CURRENT_DIR=$(pwd)

# 获取脚本所在目录的绝对路径
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)

# 根据脚本目录计算项目根目录路径
if [[ "$SCRIPT_DIR" == */scripts/tools ]]; then
  # 如果脚本位于scripts/tools目录中
  PROJECT_ROOT=$(cd "$SCRIPT_DIR/../.." && pwd)
elif [[ "$SCRIPT_DIR" == */scripts/* ]]; then
  # 如果脚本位于scripts目录或其他子目录中
  PROJECT_ROOT=$(echo "$SCRIPT_DIR" | sed 's|\(.*\)/scripts.*|\1|')
else
  # 否则假设当前目录是项目根目录
  PROJECT_ROOT=$(pwd)
fi

# 配置文件路径
CONFIG_FILE="$PROJECT_ROOT/config/backup_env.conf"

# 检查配置文件是否存在
if [ ! -f "$CONFIG_FILE" ]; then
  echo "错误: 配置文件不存在: $CONFIG_FILE"
  exit 1
fi

# 导入共用函数 - 使用绝对路径
COMMON_SCRIPT="$PROJECT_ROOT/scripts/common.sh"
if [ -f "$COMMON_SCRIPT" ]; then
  source "$COMMON_SCRIPT"
else
  echo "错误: 共用脚本不存在: $COMMON_SCRIPT"
  exit 1
fi

log_info "===== MinIO连接检查工具 ====="

# 检查MinIO配置
if [ -z "$MINIO_HOST" ] || [ -z "$MINIO_PORT" ] || [ -z "$MINIO_USER" ] || [ -z "$MINIO_PASSWORD" ] || [ -z "$MINIO_BUCKET" ]; then
    log_error "MinIO配置不完整，请检查config/backup_env.conf中的MinIO配置"
    log_info "必要的配置项:"
    echo "MINIO_HOST=$MINIO_HOST"
    echo "MINIO_PORT=$MINIO_PORT"
    echo "MINIO_USER=$MINIO_USER"
    echo "MINIO_BUCKET=$MINIO_BUCKET"
    exit 1
fi

# 检查s3cmd是否安装
if ! command -v s3cmd &> /dev/null; then
    log_warn "s3cmd未安装，正在安装..."
    apt-get update && apt-get install -y s3cmd || log_error "s3cmd安装失败"
fi

# 显示当前WAL-G配置
if [ -f "/root/.walg.json" ]; then
    log_info "当前WAL-G配置:"
    cat "/root/.walg.json" | grep -v "PASSWORD" | grep -v "SECRET"
else
    log_warn "未找到WAL-G配置文件: /root/.walg.json"
fi

# 创建临时s3cfg配置文件
TEMP_S3CFG=$(mktemp)
cat > "$TEMP_S3CFG" << EOF
[default]
access_key = $MINIO_USER
secret_key = $MINIO_PASSWORD
host_base = $MINIO_HOST:$MINIO_PORT
host_bucket = $MINIO_HOST:$MINIO_PORT
use_https = False
signature_v2 = False
EOF

# 步骤1: 检查MinIO服务可访问性
log_info "步骤1: 检查MinIO服务可访问性..."
if curl -s --connect-timeout 5 "http://$MINIO_HOST:$MINIO_PORT/minio/health/live" > /dev/null; then
    log_success "MinIO服务连接成功: http://$MINIO_HOST:$MINIO_PORT"
else
    log_error "无法连接到MinIO服务: http://$MINIO_HOST:$MINIO_PORT"
    log_info "请检查以下内容:"
    log_info "1. MinIO服务是否已启动"
    log_info "2. 主机名和端口是否正确"
    log_info "3. 网络连接是否正常"
    log_info "4. 防火墙是否阻止连接"
    exit 1
fi

# 步骤2: 验证MinIO凭证
log_info "步骤2: 验证MinIO凭证..."
if s3cmd -c "$TEMP_S3CFG" ls > /dev/null 2>&1; then
    log_success "MinIO凭证验证成功"
else
    log_error "MinIO凭证验证失败"
    log_info "请检查以下内容:"
    log_info "1. 用户名和密码是否正确"
    log_info "2. 用户是否有足够的权限"

    # 尝试添加用户
    log_info "是否要尝试创建新的MinIO用户? (y/n)"
    read -r answer
    if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
        log_info "注意: 此操作需要MinIO管理员权限"
        log_info "请输入MinIO管理员用户名:"
        read -r admin_user
        log_info "请输入MinIO管理员密码:"
        read -rs admin_pass

        # 创建临时管理员配置文件
        ADMIN_S3CFG=$(mktemp)
        cat > "$ADMIN_S3CFG" << EOF
[default]
access_key = $admin_user
secret_key = $admin_pass
host_base = $MINIO_HOST:$MINIO_PORT
host_bucket = $MINIO_HOST:$MINIO_PORT
use_https = False
signature_v2 = False
EOF

        # 尝试创建用户
        log_info "尝试创建用户: $MINIO_USER"
        # 此处需要管理员API调用，使用curl直接调用MinIO Admin API
        # 注意: 这只是一个示例，实际上MinIO的API可能更复杂
        curl -s -X PUT "http://$MINIO_HOST:$MINIO_PORT/minio/admin/v3/add-user" \
             -H "Authorization: Basic $(echo -n "$admin_user:$admin_pass" | base64)" \
             -d "{\"accessKey\":\"$MINIO_USER\",\"secretKey\":\"$MINIO_PASSWORD\"}" > /dev/null 2>&1

        # 清理临时文件
        rm -f "$ADMIN_S3CFG"

        # 重新验证
        if s3cmd -c "$TEMP_S3CFG" ls > /dev/null 2>&1; then
            log_success "用户创建成功且凭证验证通过"
        else
            log_error "用户创建后凭证验证仍然失败"
            exit 1
        fi
    else
        exit 1
    fi
fi

# 步骤3: 检查存储桶是否存在
log_info "步骤3: 检查存储桶是否存在..."
if s3cmd -c "$TEMP_S3CFG" ls "s3://$MINIO_BUCKET" > /dev/null 2>&1; then
    log_success "存储桶存在: $MINIO_BUCKET"
else
    log_warn "存储桶不存在: $MINIO_BUCKET"
    log_info "是否创建存储桶? (y/n)"
    read -r answer
    if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
        if s3cmd -c "$TEMP_S3CFG" mb "s3://$MINIO_BUCKET"; then
            log_success "存储桶创建成功: $MINIO_BUCKET"
        else
            log_error "存储桶创建失败，可能没有足够的权限"
            exit 1
        fi
    else
        log_error "存储桶不存在且未创建，备份将无法进行"
        exit 1
    fi
fi

# 步骤4: 检查和创建所需的目录结构
log_info "步骤4: 检查和创建目录结构..."
S3_DIRS=("$MINIO_FULL_PREFIX" "$MINIO_DIFF_PREFIX" "$MINIO_FULL_PREFIX/basebackups_005" "$MINIO_FULL_PREFIX/wal_005")

# 创建一个空临时文件
echo "" > /tmp/empty_file

for dir in "${S3_DIRS[@]}"; do
    log_info "检查目录: $dir"

    # 尝试列出目录内容
    if s3cmd -c "$TEMP_S3CFG" ls "s3://$MINIO_BUCKET/$dir/" > /dev/null 2>&1; then
        log_success "目录存在: $dir"
    else
        log_warn "目录不存在: $dir"
        log_info "创建目录: $dir"

        # 在MinIO中，目录实际上是通过上传文件来创建的
        if s3cmd -c "$TEMP_S3CFG" put /tmp/empty_file "s3://$MINIO_BUCKET/$dir/.keep" > /dev/null 2>&1; then
            log_success "目录创建成功: $dir"
        else
            log_error "目录创建失败: $dir"
            exit 1
        fi
    fi
done

# 步骤5: 测试WAL-G连接
log_info "步骤5: 测试WAL-G连接..."
wal-g backup-list 2>&1 | tee /tmp/walg_test_output

# 检查输出是否包含备份名称模式或"No backups found"消息
if grep -E 'base_[0-9]{24}|No backups found' /tmp/walg_test_output > /dev/null; then
    log_success "WAL-G连接测试成功"
else
    # 检查是否有错误信息
    if grep -i "error\|exception\|failed\|denied" /tmp/walg_test_output > /dev/null; then
        log_error "WAL-G连接测试失败"
        cat /tmp/walg_test_output

    if grep -q "AccessDenied" /tmp/walg_test_output; then
        log_error "WAL-G连接测试失败: 访问被拒绝"
        log_info "请检查MinIO用户权限和存储桶策略"

        # 尝试设置公共访问策略
        log_info "是否要为存储桶设置访问策略? (y/n)"
        read -r answer
        if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
            # 创建公共访问策略
            cat > /tmp/bucket_policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"AWS": ["*"]},
      "Action": ["s3:GetBucketLocation", "s3:ListBucket"],
      "Resource": ["arn:aws:s3:::$MINIO_BUCKET"]
    },
    {
      "Effect": "Allow",
      "Principal": {"AWS": ["*"]},
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": ["arn:aws:s3:::$MINIO_BUCKET/*"]
    }
  ]
}
EOF

            # 设置存储桶策略
            s3cmd -c "$TEMP_S3CFG" setpolicy /tmp/bucket_policy.json s3://$MINIO_BUCKET

            # 重新测试
            log_info "重新测试WAL-G连接..."
            wal-g backup-list 2>&1 | tee /tmp/walg_test_output

                if grep -E 'base_[0-9]{24}|No backups found' /tmp/walg_test_output > /dev/null; then
                log_success "策略设置后WAL-G连接测试成功"
            else
                log_error "策略设置后WAL-G连接测试仍然失败"
                cat /tmp/walg_test_output
            fi
        fi
        fi
    fi
fi

# 清理临时文件
rm -f "$TEMP_S3CFG" /tmp/empty_file /tmp/walg_test_output /tmp/bucket_policy.json 2>/dev/null

log_info "===== MinIO连接检查完成 ====="
if [ $? -eq 0 ]; then
    log_success "MinIO连接和配置检查成功"
    exit 0
else
    log_error "MinIO连接和配置检查存在问题，请解决上述问题"
    exit 1
fi
